module Mod_Parallele


implicit none

INCLUDE "mpif.h"

	INTEGER :: comm1d,code
	INTEGER :: rang !Numero du sous domaine
	INTEGER :: nb_procs !Nombre de processus
	INTEGER, PARAMETER                        :: ndims = 1
  INTEGER, DIMENSION(1)                     :: dims
  LOGICAL, DIMENSION(1)                     :: periods
  LOGICAL, PARAMETER                        :: reorganisation = .false.
	INTEGER, DIMENSION(2) :: voisin
	INTEGER, PARAMETER    :: W=1, E=2
  INTEGER, PARAMETER    :: etiquette=100
	INTEGER, DIMENSION(MPI_STATUS_SIZE)    :: statut
	INTEGER,parameter :: taille_rec=2

contains

!!//////////////////////////////////////////////////////////////////////

	subroutine init()
	
	implicit none

		!Initialisation de MPI
		CALL MPI_INIT(code)

		!Savoir quel processeur je suis
	!	CALL MPI_COMM_RANK( MPI_COMM_WORLD, rang, code)

		!Connaitre le nombre total de processus
		CALL MPI_COMM_SIZE( MPI_COMM_WORLD, nb_procs, code)


		dims(:)= 0
	  CALL MPI_DIMS_CREATE( nb_procs, ndims, dims, code )

		periods(:) = .false.
    CALL MPI_CART_CREATE( MPI_COMM_WORLD, ndims, dims, periods, &
                        reorganisation, comm1d, code )

		!Savoir quel processeur je suis
		CALL MPI_COMM_RANK( comm1d, rang, code)

		call MPI_CART_SHIFT(comm1d,0,1,voisin(W),voisin(E),code)


	end subroutine

!!//////////////////////////////////////////////////////////////////////


	subroutine fin()

	implicit none
	
	CALL MPI_COMM_FREE( comm1d, code )

	!Desactivation de MPI
		CALL MPI_FINALIZE(code)

	end subroutine

!!//////////////////////////////////////////////////////////////////////
subroutine communique()
	use Mod_MARdim
	use Mod_MARdyn__Hyd

	implicit none


	!Envoi au voisin W et  reception du voisin E 
	do j = 0,myy  
  CALL MPI_SENDRECV( ps_dyn(taille_rec,j), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette,  ps_dyn(mxx+1-taille_rec,j), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette, comm1d, statut, code)


  CALL MPI_SENDRECV( ps_dyn(mxx+1-2*taille_rec,j), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+1,   ps_dyn(0,j), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+1, comm1d, statut, code)

	CALL MPI_SENDRECV( psndyn(taille_rec,j), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+2,  psndyn(mxx+1-taille_rec,j), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+2, comm1d, statut, code)


  CALL MPI_SENDRECV( psndyn(mxx+1-2*taille_rec,j), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+3,   psndyn(0,j), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+3, comm1d, statut, code)

	end do

	do k = 1,mzz	
	do j = 0,myy  
  CALL MPI_SENDRECV( ua_dyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+4,  ua_dyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+4, comm1d, statut, code)

  CALL MPI_SENDRECV( ua_dyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+5,   ua_dyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+5, comm1d, statut, code)

	CALL MPI_SENDRECV( uandyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+6,  uandyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+6, comm1d, statut, code)

  CALL MPI_SENDRECV( uandyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+7,   uandyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+7, comm1d, statut, code)

                             !!!!!!!!!!!!!!!!!!!!!!!

	CALL MPI_SENDRECV( va_dyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+8,  va_dyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+8, comm1d, statut, code)

  CALL MPI_SENDRECV( va_dyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+9,   va_dyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+9, comm1d, statut, code)

	CALL MPI_SENDRECV( vandyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+10,  vandyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+10, comm1d, statut, code)

  CALL MPI_SENDRECV( vandyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+11,   vandyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+11, comm1d, statut, code)

!!!dU_dyn et autre


                               !!!!!!!!!!!!!!!!!!!!!!!

  CALL MPI_SENDRECV( PT_dyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+12,  PT_dyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+12, comm1d, statut, code)

  CALL MPI_SENDRECV( PT_dyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+13,   PT_dyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+13, comm1d, statut, code)

	CALL MPI_SENDRECV( PTndyn(taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION,  voisin(W), &
       etiquette+14,  PTndyn(mxx+1-taille_rec,j,k), taille_rec,MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+14, comm1d, statut, code)

  CALL MPI_SENDRECV( PTndyn(mxx+1-2*taille_rec,j,k), taille_rec, MPI_DOUBLE_PRECISION, voisin(E), &
       etiquette+15,   PTndyn(0,j,k), taille_rec,  MPI_DOUBLE_PRECISION, voisin(W), &
      etiquette+15, comm1d, statut, code)


	end do
	end do





end subroutine

!!//////////////////////////////////////////////////////////////////////




	subroutine recup_Ini(xx,topo,lonh,latr,sol)
	use Mod_Real
	use Mod_MARdim
	use Mod_MARdyn_grid
	use Mod_MARGEo_grid 

	implicit none

	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs)     ::   xx                    ! x-coordinate   [m]
	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs,0:myy)     ::   topo , lonh , latr , sol
	integer :: sizeloc

	sizeloc=mxx+1-2*taille_rec


	call MPI_GATHER(xm(taille_rec),sizeloc,MPI_DOUBLE_PRECISION,xx, &
	     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)


	do j = 0,myy
		call MPI_GATHER(GEtopo(taille_rec,j),sizeloc,MPI_DOUBLE_PRECISION,topo(:,j), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)

		call MPI_GATHER(GElonh(taille_rec,j),sizeloc,MPI_DOUBLE_PRECISION,lonh(:,j), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)

		call MPI_GATHER(GElatr(taille_rec,j),sizeloc,MPI_DOUBLE_PRECISION,latr(:,j), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)

		call MPI_GATHER(GE_sol(taille_rec,j),sizeloc,MPI_DOUBLE_PRECISION,sol(:,j), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)

	end do


end subroutine


!//////////////////////////////////////////////////////////////////////

	subroutine recup_Hyd(udyn , vdyn , Tdyn, PTdyn, wdyn, psndynG, gZ_dynG)
	use Mod_Real
	use Mod_MARdim
	use Mod_MARdyn__Hyd

	implicit none

	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs,0:myy,  mzz) :: udyn , vdyn , Tdyn, PTdyn
	!real(kind=real8), dimension(0:mxx*nb_procs-1,0:my,  mzz) :: wdyn !!!
	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs,0:my,  mzz) :: wdyn !!!
	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs,0:myy)       :: psndynG
	real(kind=real8), dimension(1:(mxx+1-2*taille_rec)*nb_procs,0:myy,  mzz) :: gZ_dynG
	integer :: sizeloc

	sizeloc=mxx+1-2*taille_rec



	do k = 1,mzz
	do j = 0,myy
		call MPI_GATHER(uandyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,udyn(:,j,k), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
		call MPI_GATHER(vandyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,vdyn(:,j,k), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
		call MPI_GATHER(Ta_dyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,Tdyn(:,j,k), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
		call MPI_GATHER(PT_dyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,PTdyn(:,j,k), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
		call MPI_GATHER(gZ_dyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,gZ_dynG(:,j,k), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
	end do
	do j = 0,my
		call MPI_GATHER(wa_dyn(taille_rec,j,k),sizeloc,MPI_DOUBLE_PRECISION,wdyn(:,j,k), &
		    sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
	end do
	end do

	do j = 0,myy
		call MPI_GATHER(psndyn(taille_rec,j),sizeloc,MPI_DOUBLE_PRECISION,psndynG(:,j), &
		     sizeloc,MPI_DOUBLE_PRECISION,0,comm1d,code)
	end do


end subroutine


!///////////////////////////////////////////////////////////////////


end
